/**
 * 
 */
package com.scpii.universal.hibernate.dao;

import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.scpii.universal.hibernate.entity.CatelogTab;
import com.scpii.universal.hibernate.intface.BaseInterface;
import com.scpii.universal.util.Const;

/**
 * UniversalApi
 * 
 * @author 甘建新 2012-7-15下午11:22:03
 * @param <T>
 */
public class BaseDao<T> extends HibernateDaoSupport implements BaseInterface<T> {
	private Class<T> entity;

	public BaseDao() {

	}

	public BaseDao(Class<T> entity) {
		this.entity = entity;
	}

	public T get(Integer id) {
		return (T) this.getHibernateTemplate().get(entity, id);
	}

	public T get(Long id) {
		return (T) this.getHibernateTemplate().get(entity, id);
	}

	public T load(Integer id) {
		return null;
	}

	public List<T> getAll() {
		return this.getHibernateTemplate().loadAll(entity);
	}

	public T get(String propertyName, Object value) {
		return null;
	}

	public List<T> getList(String propertyName, Object value) {
		return null;
	}

	public Long getTotalCount() {
		return null;
	}

	public void save(T obj) {
		this.getHibernateTemplate().save(obj);
	}

	public void update(T obj) {
		this.getHibernateTemplate().update(obj);
	}

	public void delete(T obj) {
		this.getHibernateTemplate().delete(obj);
	}

	public void delete(Integer id) {
		T t = this.get(id);
		delete(t);
	}

	public List<T> hqlGetList(String hql, Map<String, Object> argsMap) {
		if (hql != null) {
			Session session = this.getHibernateTemplate().getSessionFactory()
					.getCurrentSession();
			Query query = session.getNamedQuery(hql);
			query.setCacheable(Const.IS_CACHEABLE);
			if (argsMap != null) {
				Set set = argsMap.entrySet();
				Iterator iterator = set.iterator();
				while (iterator.hasNext()) {
					Map.Entry<String, Object> entry = (Entry<String, Object>) iterator
							.next();
					query.setParameter(entry.getKey(), entry.getValue());
				}
			}
			return (List<T>) query.list();
		}
		return null;
	}

	public void hqlUpdate(String namedHqlQuery, Map<String, Object> argsMap) {
		if (namedHqlQuery != null) {
			Session session = this.getHibernateTemplate().getSessionFactory()
					.getCurrentSession();
			Query query = session.getNamedQuery(namedHqlQuery);
			query.setCacheable(Const.IS_CACHEABLE);
			if (argsMap != null) {
				Set set = argsMap.entrySet();
				Iterator iterator = set.iterator();
				while (iterator.hasNext()) {
					Map.Entry<String, Object> entry = (Entry<String, Object>) iterator
							.next();
					query.setParameter(entry.getKey(), entry.getValue());
				}
			}
			int i = query.executeUpdate();
			logger.info("执行结果为" + i);
		}
	}

	public Long hqlGetNums(String namedHqlQuery, Map<String, Object> argsMap) {
		if (namedHqlQuery != null && namedHqlQuery.trim().length() > 0) {
			Session session = this.getHibernateTemplate().getSessionFactory()
					.getCurrentSession();
			Query query = session.getNamedQuery(namedHqlQuery);
			query.setCacheable(Const.IS_CACHEABLE);
			if (argsMap != null) {
				Set set = argsMap.entrySet();
				Iterator iterator = set.iterator();
				while (iterator.hasNext()) {
					Map.Entry<String, Object> entry = (Entry<String, Object>) iterator
							.next();
					query.setParameter(entry.getKey(), entry.getValue());
				}
			}
			List<T> tList = query.list();
			if (tList != null && tList.size() == 1) {
				return (Long) tList.get(0);
			}
		}
		return (long) 0;
	}

	public List<T> sqlGetList(String sqls, Map<String, Object> argsMap) {
		if (sqls != null && sqls.trim().length() > 0) {
			Session session = this.getHibernateTemplate().getSessionFactory()
					.getCurrentSession();
			// Query query = session.getNamedQuery(sqls);
			Query query = session.createSQLQuery(sqls).addEntity(entity);
			query.setCacheable(Const.IS_CACHEABLE);
			if (argsMap != null) {
				Set set = argsMap.entrySet();
				Iterator iterator = set.iterator();
				while (iterator.hasNext()) {
					Map.Entry<String, Object> entry = (Entry<String, Object>) iterator
							.next();
					query.setParameter(entry.getKey(), entry.getValue());
				}
			}
			return query.list();
		}
		return null;
	}

	public List sqlGetListForIndefiniteCols(String queryName,
			Map<String, Object> argsMap) {
		if (queryName != null && queryName.trim().length() > 0) {
			Session session = this.getHibernateTemplate().getSessionFactory()
					.getCurrentSession();
			Query query = session.getNamedQuery(queryName);
			query.setCacheable(Const.IS_CACHEABLE);
			if (argsMap != null) {
				Set set = argsMap.entrySet();
				Iterator iterator = set.iterator();
				while (iterator.hasNext()) {
					Map.Entry<String, Object> entry = (Entry<String, Object>) iterator
							.next();
					query.setParameter(entry.getKey(), entry.getValue());
				}
			}
			return query.list();
		}
		return null;
	}

	public void sqlUpdate(String sqls, Map<String, Object> argsMap) {
		if (sqls != null && sqls.trim().length() > 0) {
			Session session = this.getHibernateTemplate().getSessionFactory()
					.getCurrentSession();
			Query query = session.createSQLQuery(sqls).addEntity(entity);
			// Query query = session.getNamedQuery(sqls);
			query.setCacheable(Const.IS_CACHEABLE);
			if (argsMap != null) {
				Set set = argsMap.entrySet();
				Iterator iterator = set.iterator();
				while (iterator.hasNext()) {
					Map.Entry<String, Object> entry = (Entry<String, Object>) iterator
							.next();
					query.setParameter(entry.getKey(), entry.getValue());
				}
			}
			int i = query.executeUpdate();
			logger.info("执行结果为" + i);
		}
	}

	public Long sqlGetNum(String sqls, Map<String, Object> argsMap) {
		if (sqls != null && !sqls.trim().equals("")) {
			Session session = super.getHibernateTemplate().getSessionFactory()
					.getCurrentSession();
			Query query = session.createSQLQuery(sqls);
			if (argsMap != null) {
				Set set = argsMap.entrySet();
				Iterator iterator = set.iterator();
				while (iterator.hasNext()) {
					Map.Entry<String, Object> entry = (Entry<String, Object>) iterator
							.next();
					query.setParameter(entry.getKey(), entry.getValue());
				}
				List list = query.list();
				if (list != null && list.size() == 1) {
					return (Long) list.get(0);
				}
			}
		}
		return (long) 0;
	}

	/**
	 * 用于计算全部结果集的数量，可以分为多少页
	 */
	public Integer getRecordPageNum(int recordNum, int recordNumPerPage) {
		int pageNum = 0;
		if (recordNum > 0 && recordNum > recordNumPerPage) {
			int mod = recordNum % recordNumPerPage;
			if (mod == 0) {
				pageNum = recordNum / recordNumPerPage;
			} else {
				pageNum = recordNum / recordNumPerPage + 1;
			}
		} else {
			return 1;
		}
		return pageNum;
	}

	public List<T> findByHql(final String hql, final Map<String, Object> argsMap) {
		List<T> lstResult = null;
		lstResult = getHibernateTemplate().executeFind(
				new HibernateCallback<T>() {
					@Override
					public T doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery(hql);
						query.setCacheable(Const.IS_CACHEABLE);
						if (argsMap != null) {
							Set<String> keySet = argsMap.keySet();
							for (String string : keySet) {
								Object obj = argsMap.get(string);
								if (obj instanceof Collection<?>) {
									query.setParameterList(string,
											(Collection<?>) obj);
								} else if (obj instanceof Object[]) {
									query.setParameterList(string,
											(Object[]) obj);
								} else {
									query.setParameter(string, obj);
								}
							}
						}
						return (T) query.list();
					}

				});
		return lstResult;
	}

	/**
	 * 分页查询
	 * 
	 * @author Taylor 2012-9-18 下午02:06:04
	 * @param pageNo
	 * @param pageSize
	 * @param sql
	 * @param map
	 * @return List<T>
	 * @throws ClassNotFoundException
	 */
	public List<T> findBySql(final int pageNo, final int pageSize,
			final String sql, final Map<String, Object> map)
			throws ClassNotFoundException {
		List<T> lstResult = null;
		lstResult = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				SQLQuery query = session.createSQLQuery(sql).addEntity(entity);
				query.setCacheable(Const.IS_CACHEABLE);
				if (map != null) {
					Iterator<String> it = map.keySet().iterator();
					while (it.hasNext()) {
						Object key = it.next();
						query.setParameter(key.toString(), map.get(key));
					}
				}
				if (pageNo != 0) {
					query.setFirstResult((pageNo - 1) * pageSize);
					query.setMaxResults(pageSize);
				}
				return query.list();
			}
		});
		return lstResult;
	}

	/**
	 * 根据分类ID和应用ID查询所有子分类
	 * 
	 * @author Taylor 2012-9-19 下午06:25:30
	 * @param id
	 * @return List<CatelogTab>
	 */
	public List<CatelogTab> getSubordinateCatelogs(int id) {
		StringBuffer sql = new StringBuffer();
		sql.append("select {cate.*} from CATELOG_TAB cate");
		sql.append(" where cate.INT_DELETE_SIGN=0");
		sql.append(" start with cate.INT_CATE_ID=?");
		sql.append(" connect by prior cate.INT_CATE_ID=cate.INT_PARENT_CATE_ID");
		return getHibernateTemplate().getSessionFactory().getCurrentSession()
				.createSQLQuery(sql.toString())
				.addEntity("cate", CatelogTab.class).setParameter(0, id).list();
	}

	/**
	 * 调用Oracle的存储过程或者函数
	 * 
	 * @return
	 * @author 甘建新 2012-9-21下午02:20:42
	 */
	public Integer executeFunction(String procOrFuncSql,
			Map<String, Object> argsMap) {
		Session session = getHibernateTemplate().getSessionFactory()
				.openSession();
		SQLQuery sqlQuery = session.createSQLQuery(procOrFuncSql);
		if (argsMap != null) {
			Set set = argsMap.entrySet();
			Iterator iterator = set.iterator();
			while (iterator.hasNext()) {
				Map.Entry<String, Object> entry = (Entry<String, Object>) iterator
						.next();
				sqlQuery.setParameter(entry.getKey(), entry.getValue());
			}
		}
		List list = sqlQuery.list();
		if (list != null && list.size() > 0) {
			return (Integer) list.get(0);
		}
		return 0;
	}

	public <S> S executeCallBack(HibernateCallback<S> param) {
		return getHibernateTemplate().execute(param);
	}
}
